package com.sunny.blog.common.config;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.servlet.ServletUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.sunny.blog.common.entity.SysConstant;
import com.sunny.blog.pojo.IpInfoBean;
import com.sunny.blog.pojo.SysLog;
import com.sunny.blog.service.BlogLogInterface;
import com.sunny.blog.service.ISysLogService;
import com.sunny.blog.service.OpenApiService;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

/**
 * @ClassName: SysLogAspect
 * @Description: 日志切面类
 * @Author: sunt
 * @Date: 2020/5/22 10:20
 * @Version 1.0
 **/
@Aspect
@Component
@Slf4j
public class SysLogAspect {

    @Autowired
    private ISysLogService sysLogService;
    @Autowired
    private HttpServletRequest request;
    @Autowired
    private OpenApiService openApiService;
    @Autowired
    private RabbitTemplate rabbitTemplate;


    //定义切点 @Pointcut
    //在注解的位置切入代码
    @Pointcut("@annotation( com.sunny.blog.service.BlogLogInterface)")
    public void logPoinCut() {
    }

    //切面 配置通知
    @AfterReturning("logPoinCut()")
    public void saveSysLog(JoinPoint joinPoint) {
        SysLog sysLog = new SysLog();
        //从切面织入点处通过反射机制获取织入点处的方法
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        String className = joinPoint.getTarget().getClass().getName();
        String methodName = method.getName();
        //获取操作,Controller注解指定的值
        BlogLogInterface blogLogInterface = method.getAnnotation(BlogLogInterface.class);
        if (ObjectUtil.isNotNull(blogLogInterface)) {
            String value = blogLogInterface.value();
            sysLog.setReqType(value);
        }
        //请求的参数
        Object[] args = joinPoint.getArgs();
        String params = JSONUtil.toJsonStr(args);
        if(StrUtil.equals(SysConstant.QUERY_BLOG_DETAIL,blogLogInterface.value())) {
            String id = parseStrArray(params);
            methodName += "?params=" + id;
        }

        sysLog.setReqMethod(className + "." + methodName);
        sysLog.setReqParam(params);
        IpInfoBean ipInfoBean = openApiService.queryIpInfo(ServletUtil.getClientIP(request));
        sysLog.setReqIp(ipInfoBean.getIp());
        sysLog.setIpInfo(ipInfoBean.getAddr());
        sysLog.setReqTime(DateUtil.date());

        log.info("----------->aop切面记录用户日志操作发送MQ,ip:{}",sysLog.getReqIp());
        sysLogService.sendDelayMsgToMQ(SysConstant.SYS_LOG_DELAY_EXCHANGE,SysConstant.SYS_LOG_DELAY_KEY,JSONUtil.toJsonStr(sysLog),10*60*1000);//10分钟
    }

    private String parseStrArray(String s) {
        JSONArray array = JSONUtil.parseArray(s);
        List<ArrayList> arrayLists = JSONUtil.toList(array, ArrayList.class);
        for (ArrayList arrayList : arrayLists) {
            JSONObject o = (JSONObject) arrayList.get(0);
            return o.getStr("id");
        }
        return null;
    }
}
